iT邦幫忙

2021 iThome 鐵人賽

DAY 22
1
Software Development

從零開始Reactive Programming- Spring系列 第 23

[Day 22] Reactive Programming - Spring WebFlux(Hello World) Part 2

  • 分享至 

  • xImage
  •  

前言

在上一篇成功實作最基本的WebFlux功能,看到了一些有點熟悉又有點陌生的新朋友,在這邊補充說明。

Handler&Router

Spring 同樣保留了支援annotation-based,依然可以使用熟悉的Spring MVC各式annotation(@RequestMapping@RestController...),那為什麼需要有Handler&Router
首先如果你對原本的annotation感到十分親切,當然可以繼續採用原本的寫法,一樣直覺好用,但畢竟Reactive我們希望能夠Functional,所以如果是一個新的專案想要嘗試Reactive Spring,那擁抱FunctionalHandler&Router是一個不錯的選擇。

ServerResponse & ServerRequest 

ServerResponse類似以前的ResponseEntity,含有statusheaderbody,提供了更多方法更加的FunctionalServerRequest 在原有的Spring MVC當中並沒有這樣的角色,
Spring透過各式annotation(@RequestMapping@Valid)自動幫你帶入指定的Object,雖然非常方便,但其實如果你沒有深入去了解,是沒辦法從程式碼去連結到行為與資料(都是背後處理掉),而且不容易繼承來進行客製化,annotation如果要取得路徑或是其他資料需要透過反射(reflection),相對就會有效能與type erasure的問題,ServerRequestServerResponse 改為Functional的風格則會讓過程更佳清楚。


public class PersonHandler { 
    private final PersonRepository repository; 
    public PersonHandler(PersonRepository repository) { 
        this.repository = repository; 
    } 
    public Mono<ServerResponse> listPeople(ServerRequest request) {  
        Flux<Person> people = repository.allPeople(); 
        return ok().contentType(APPLICATION_JSON).body(people, Person.class); 
    } 
    public Mono<ServerResponse> createPerson(ServerRequest request) {  
        Mono<Person> person = request.bodyToMono(Person.class); 
        return ok().build(repository.savePerson(person)); 
    } 
    public Mono<ServerResponse> getPerson(ServerRequest request) {  
        int personId = Integer.valueOf(request.pathVariable("id")); 
        return repository.getPerson(personId) 
            .flatMap(person -> ok().contentType(APPLICATION_JSON).bodyValue(person)) 
            .switchIfEmpty(ServerResponse.notFound().build()); 
    } 
}

WebClient

類似於RestTemplate,是一個functional的Api,支援non-blocking/blocking、streaming,寫起來更加的流暢。透過Codecs來處理(serializing /deserializing )我們需要使用的物件,Codecs 同樣類似於Spring MVCHttpMessageConverter

WebClient webClient = WebClient.builder() 
        .codecs(configurer -> { 
                CustomDecoder decoder = new CustomDecoder(); 
                configurer.customCodecs().registerWithDefaultConfig(decoder); 
        }) 
        .build();

其他

透過ntellij動demo專案時發生一個錯誤,推測可能是啟動JMX(管理JVM的內的entity,視覺化的呈現)時pringApplication未開啟完成導致

javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication

參考stackoverflow回答則可正常執行https://stackoverflow.com/questions/50436108/javax-management-instancenotfoundexception-org-springframework-boottype-admin

  • Edit Configurations
  • choose your project
  • remove the 'Enable launch optimization' and 'Enable JMX agent' checkboxes
    除了以上方法,或許是intellij版本比較舊,相容沒有做好,升級後就沒有這個問題了。

結語

接下來會稍微深入一點來看Handler&Router。

開始到了文章越來越難產的一個階段,最後八篇!

資料來源

上一篇
[Day 21] Reactive Programming - Spring WebFlux(Hello World) Part 1
下一篇
[Day 23] Reactive Programming - Spring WebFlux(Handler)
系列文
從零開始Reactive Programming- Spring32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言